import json
from django.conf import settings
from movies.models import Movie, Rating
from .llm_factory import LLMFactory

class AIRecommendationService:
    """使用大模型API进行电影推荐的服务类"""
    
    def __init__(self):
        self.llm_service = LLMFactory.get_llm_service()
        
    def get_personalized_recommendations(self, user, limit=5):
        """
        根据用户的观影历史和评分获取个性化推荐
        """
        # 获取用户评分历史
        user_ratings = Rating.objects.filter(user=user).select_related('movie')
        
        if not user_ratings.exists():
            return self.get_popular_recommendations(limit)
        
        # 构建用户观影历史
        liked_movies = []
        disliked_movies = []
        
        for rating in user_ratings:
            movie_info = {
                'title': rating.movie.title,
                'year': rating.movie.year,
                'genres': [g.name for g in rating.movie.genres.all()]
            }
            
            if rating.rating >= 4:  # 4-5分被视为喜欢
                liked_movies.append(movie_info)
            elif rating.rating <= 2:  # 1-2分被视为不喜欢
                disliked_movies.append(movie_info)
        
        # 构建提示
        prompt = self._build_recommendation_prompt(liked_movies, disliked_movies, limit)
        
        try:
            # 调用大模型API
            messages = [
                {"role": "system", "content": "你是一个专业的电影推荐助手，基于用户的电影品味提供精准推荐。"},
                {"role": "user", "content": prompt}
            ]
            
            response = self.llm_service.chat_completion(
                messages=messages,
                temperature=0.7,
                max_tokens=800
            )
            
            if response['status'] == 'success':
                # 解析推荐结果
                return self._parse_recommendations(response['content'])
            else:
                print(f"调用大模型API出错: {response['content']}")
                return self.get_popular_recommendations(limit)
                
        except Exception as e:
            print(f"调用大模型API出错: {str(e)}")
            return self.get_popular_recommendations(limit)
    
    def get_mood_based_recommendations(self, mood_description, limit=5):
        """
        根据用户描述的心情或场景推荐电影
        """
        prompt = f"""
        请根据以下心情或场景描述推荐{limit}部最合适的电影：
        
        "{mood_description}"
        
        对于每部电影，请提供以下信息：
        1. 电影名称
        2. 发行年份
        3. 简短推荐理由
        4. 为什么这部电影适合这种心情
        
        以JSON格式返回结果，每部电影包含title, year, reason字段。
        """
        
        try:
            messages = [
                {"role": "system", "content": "你是一个专业的电影推荐助手，能根据用户的心情和场景推荐最合适的电影。"},
                {"role": "user", "content": prompt}
            ]
            
            response = self.llm_service.chat_completion(
                messages=messages,
                temperature=0.7,
                max_tokens=800
            )
            
            if response['status'] == 'success':
                # 解析推荐结果
                return self._parse_recommendations(response['content'])
            else:
                print(f"调用大模型API出错: {response['content']}")
                return []
                
        except Exception as e:
            print(f"调用大模型API出错: {str(e)}")
            return []
    
    def analyze_movie(self, movie):
        """
        对电影进行深度分析
        """
        genres = ", ".join([g.name for g in movie.genres.all()])
        
        prompt = f"""
        请对以下电影进行专业的深度分析：
        
        电影名称: {movie.title}
        发行年份: {movie.year}
        类型: {genres}
        简介: {movie.description}
        
        请在分析中包含以下方面：
        1. 电影背景和历史地位
        2. 导演风格和创作意图
        3. 主题分析
        4. 该电影最出彩的方面
        5. 如果喜欢这部电影，还可能喜欢哪些类似电影（列出3-5部）
        
        以专业影评人的口吻撰写，但要确保内容通俗易懂。
        """
        
        try:
            messages = [
                {"role": "system", "content": "你是一个专业的电影评论家，擅长电影分析和解读。"},
                {"role": "user", "content": prompt}
            ]
            
            response = self.llm_service.chat_completion(
                messages=messages,
                temperature=0.7,
                max_tokens=1000
            )
            
            if response['status'] == 'success':
                return response['content']
            else:
                return "抱歉，目前无法获取电影分析。"
                
        except Exception as e:
            print(f"调用大模型API出错: {str(e)}")
            return "抱歉，目前无法获取电影分析。"
    
    def get_similar_movies(self, movie_title, limit=5):
        """
        根据电影名称查找相似电影
        """
        try:
            movie = Movie.objects.get(title__icontains=movie_title)
            genres = ", ".join([g.name for g in movie.genres.all()])
            
            prompt = f"""
            请推荐{limit}部与电影《{movie.title}》({movie.year})相似的电影。
            电影类型: {genres}
            电影简介: {movie.description}
            
            对于每部推荐的电影，请提供：
            1. 电影名称
            2. 发行年份
            3. 与原电影的相似点
            
            以JSON格式返回，包含title, year, similarity_reason字段。
            """
            
            messages = [
                {"role": "system", "content": "你是一个电影专家，精通电影之间的风格、主题和叙事相似性。"},
                {"role": "user", "content": prompt}
            ]
            
            response = self.llm_service.chat_completion(
                messages=messages,
                temperature=0.7,
                max_tokens=800
            )
            
            if response['status'] == 'success':
                return self._parse_recommendations(response['content'])
            else:
                return []
                
        except Movie.DoesNotExist:
            return []
        except Exception as e:
            print(f"调用大模型API出错: {str(e)}")
            return []
    
    def get_popular_recommendations(self, limit=5):
        """
        获取热门电影推荐（作为备选方案）
        """
        # 从数据库获取评分最高的电影
        top_movies = Movie.objects.order_by('-vote_average')[:limit]
        
        recommendations = []
        for movie in top_movies:
            genres = [g.name for g in movie.genres.all()]
            recommendations.append({
                'title': movie.title,
                'year': movie.year,
                'reason': f"这是一部深受观众喜爱的{'/'.join(genres)}电影。"
            })
        
        return recommendations
    
    def _build_recommendation_prompt(self, liked_movies, disliked_movies, limit):
        """构建用于推荐的提示"""
        prompt = f"""
        我需要{limit}部电影推荐。请根据我喜欢和不喜欢的电影列表给出推荐。
        
        我喜欢的电影:
        """
        
        for movie in liked_movies:
            prompt += f"- {movie['title']} ({movie['year']}), 类型: {', '.join(movie['genres'])}\n"
        
        if disliked_movies:
            prompt += "\n我不喜欢的电影:\n"
            for movie in disliked_movies:
                prompt += f"- {movie['title']} ({movie['year']}), 类型: {', '.join(movie['genres'])}\n"
        
        prompt += f"""
        请推荐{limit}部我可能会喜欢的电影，但不要包括我已经看过的电影。
        
        对于每部推荐的电影，请提供：
        1. 电影名称
        2. 发行年份
        3. 推荐理由（为什么基于我的品味会喜欢这部电影）
        
        以JSON格式返回结果，每部电影包含title, year, reason字段。
        """
        
        return prompt
    
    def _parse_recommendations(self, text):
        """从大模型返回的文本中解析出推荐电影"""
        try:
            # 尝试直接解析JSON
            if '{' in text and '}' in text:
                # 提取JSON部分
                json_parts = []
                in_json = False
                braces_count = 0
                
                for line in text.split('\n'):
                    if '{' in line:
                        in_json = True
                        braces_count += line.count('{') - line.count('}')
                        json_parts.append(line)
                    elif in_json:
                        json_parts.append(line)
                        braces_count += line.count('{') - line.count('}')
                        if braces_count == 0:
                            in_json = False
                
                json_text = '\n'.join(json_parts)
                
                # 尝试找到JSON数组
                if '[' in json_text and ']' in json_text:
                    start_idx = json_text.find('[')
                    end_idx = json_text.rfind(']') + 1
                    json_str = json_text[start_idx:end_idx]
                    return json.loads(json_str)
                
                # 尝试找到JSON对象并组成数组
                elif '{' in json_text and '}' in json_text:
                    # 分离多个JSON对象
                    objects = []
                    obj_start = None
                    brace_count = 0
                    
                    for i, char in enumerate(json_text):
                        if char == '{':
                            if brace_count == 0:
                                obj_start = i
                            brace_count += 1
                        elif char == '}':
                            brace_count -= 1
                            if brace_count == 0 and obj_start is not None:
                                objects.append(json_text[obj_start:i+1])
                                obj_start = None
                    
                    # 解析每个对象
                    parsed_objects = []
                    for obj in objects:
                        try:
                            parsed = json.loads(obj)
                            parsed_objects.append(parsed)
                        except:
                            pass
                    
                    return parsed_objects
            
            # 如果无法解析JSON，尝试以结构化方式提取信息
            movies = []
            current_movie = {}
            lines = text.split('\n')
            
            for line in lines:
                line = line.strip()
                if not line:
                    continue
                    
                # 尝试识别电影标题和年份
                if ':' in line and len(line) < 100:  # 可能是一个键值对
                    key, value = line.split(':', 1)
                    key = key.strip().lower()
                    value = value.strip()
                    
                    if key in ['电影', '片名', '标题', 'title', '名称', '电影名称', '电影名', '片名']:
                        if current_movie and 'title' in current_movie:  # 已经有一部电影了
                            movies.append(current_movie)
                            current_movie = {}
                        # 处理可能包含年份的标题，如 "电影: 肖申克的救赎 (1994)"
                        if '(' in value and ')' in value and value.rfind('(') > value.rfind(')'):
                            title_part = value[:value.rfind('(')].strip()
                            year_part = value[value.rfind('(')+1:value.rfind(')')].strip()
                            if year_part.isdigit():
                                current_movie['title'] = title_part
                                current_movie['year'] = int(year_part)
                            else:
                                current_movie['title'] = value
                        else:
                            current_movie['title'] = value
                    elif key in ['年份', 'year', '发行年份', '上映年份']:
                        try:
                            # 提取数字
                            import re
                            year_match = re.search(r'\d{4}', value)
                            if year_match:
                                current_movie['year'] = int(year_match.group())
                        except:
                            pass
                    elif key in ['理由', '推荐理由', 'reason', '原因', '推荐原因', 'similarity_reason']:
                        current_movie['reason'] = value
                
            # 添加最后一部电影
            if current_movie and 'title' in current_movie:
                movies.append(current_movie)
            
            # 确保所有电影有必要的字段
            for movie in movies:
                if 'year' not in movie:
                    movie['year'] = 2000  # 默认年份
                if 'reason' not in movie:
                    movie['reason'] = "这是一部值得推荐的电影。"
            
            return movies
            
        except Exception as e:
            print(f"解析推荐结果失败: {str(e)}")
            print(f"原始文本: {text}")
            return [] 